<template>
  <j-modal
    :fullscreen="false"
    :switchFullscreen="true"
    :visible.sync="visible"
    :width="1200"
    title="实例详情"
    @cancel="handleCancel"
  >
    <template slot="footer">
      <a-button key="back" @click="handleCancel">关闭</a-button>
    </template>

    <a-spin :spinning="confirmLoading">
      <a-page-header
        v-if="model.instance"
        :sub-title="model.model.typeText"
        :title="model.instance.name"
      >
        <template slot="tags">
          <a-tag color="blue">
          <span v-show="model.instance.status === 'online'">
            <a-icon style="color:green;" theme="filled" title="在线" type="check-circle" />
            在线
          </span>
            <span v-show="model.instance.status === 'notActive'">
            <a-icon style="color:gray" theme="filled" title="未激活" type="close-circle" />
            未激活
          </span>
            <span v-show="model.instance.status === 'offline'">
            <a-icon style="color:red" theme="filled" title="离线" type="exclamation-circle" />
            离线
          </span>
          </a-tag>
        </template>
        <template slot="extra">
          <a-button type="primary" @click="refresh(model.instance.id)">刷新</a-button>
          <a-popconfirm v-if="'gateway,directTerminal'.includes(model.model.type)" title="确定强制下线该设备吗?" @confirm="() => forceOffline(model.instance.id)">
            <a-button type="">强制下线</a-button>
          </a-popconfirm>
        </template>
        <template class="content">
          <a-card>
            <a-descriptions size="small">
              <a-descriptions-item label="模型ID">
                {{ model.model.id }}
              </a-descriptions-item>
              <a-descriptions-item label="模型名称">
                {{ model.model.name }}
              </a-descriptions-item>
              <a-descriptions-item label="模型创建时间">
                {{ model.model.createTime }}
              </a-descriptions-item>
              <a-descriptions-item label="实例ID">
                {{ model.instance.id }}
              </a-descriptions-item>
              <a-descriptions-item label="实例名称">
                {{ model.instance.name }}
              </a-descriptions-item>
              <a-descriptions-item label="实例创建时间">
                {{ model.instance.createTime }}
              </a-descriptions-item>
            </a-descriptions>
          </a-card>
        </template>
        <template slot="footer">
          <a-tabs default-active-key="realtimeData" @change="">
            <a-tab-pane key="realtimeData" tab="实时数据">
              <a-empty v-if="!model.instanceDatas || model.instanceDatas.length <= 0" />
              <div v-else style="display: flex; flex-direction: row; flex-wrap: wrap">
                <template v-for="(deviceData, dataIndex) in model.instanceDatas">
                  <chart-card :title="deviceData.name" style="width:340px; margin: 0 10px 10px 0;">
                    <template slot="total">
                      <span>{{ deviceData.latestData.value }}</span>
                      <span v-if="deviceData.latestData.value" :title="deviceData.metadata.unitText">{{ deviceData.metadata.unit }}</span>
                    </template>
                    <div v-if="'int,float,double'.indexOf(deviceData.type) !== -1">
                      <mini-progress
                        :height="8"
                        :percentage="(deviceData.latestData.value*100/(deviceData.metadata.maxValue-deviceData.metadata.minValue)).toFixed(2)+''"
                        :target="(deviceData.latestData.value*100/(deviceData.metadata.maxValue-deviceData.metadata.minValue)).toFixed(2)+''"
                        color="rgb(19, 194, 194)" />
                    </div>
                    <div v-if="'bool'.indexOf(deviceData.type) !== -1">
                      <a-switch :checked="true" :checkedChildren="deviceData.metadata.trueText" :unCheckedChildren="deviceData.metadata.falseText" />
                    </div>
                    <div v-if="'string'.indexOf(deviceData.type) !== -1">
                      <mini-progress :height="8" :percentage="deviceData.metadata.value" :target="deviceData.metadata.maxValue" color="rgb(19, 194, 194)" />
                    </div>
                    <template slot="footer">上报时间：{{ deviceData['latestData']['reportTime'] || '暂无数据' }}</template>
                  </chart-card>
                </template>
              </div>
            </a-tab-pane>
            <a-tab-pane key="reportData" tab="历史数据">
              <a-card>
                <a-tabs default-active-key="config" @change="alarmTabsChanged">
                  <a-tab-pane key="config" tab="数据列表">
                    <DataReportList :instanceId="model.instance.id"></DataReportList>
                  </a-tab-pane>
                  <a-tab-pane key="record" force-render tab="数据图表">
                    <DataReportChart :instanceId="model.instance.id"></DataReportChart>
                  </a-tab-pane>
                </a-tabs>
              </a-card>
            </a-tab-pane>
            <a-tab-pane key="functionConfig" tab="功能配置">
              <a-card v-if="model.functions && model.functions.length > 0">
                <a-form-model
                    ref="functionInvokeForm"
                    :label-col="labelCol"
                    :model="model"
                    :wrapper-col="wrapperCol"
                  >
                    <a-tabs tab-position="left" @change="">
                      <template v-if="model.functions">
                        <a-tab-pane v-for="(func, funcIndex) in model.functions" v-if="func" :key="func.code" :tab="func.name">
                          <a-tag>{{ func.type }}</a-tag>
                          <a-card v-if="func.inputParams" size="small" style="margin-top: 16px" title="输入参数">
                            <template v-for="(inputParam, paramIndex) in func.inputParams">
                              <a-form-model-item
                                :key="inputParam.id"
                                :ref="inputParam.code"
                                :label="inputParam.name"
                                :prop="'functions.'+funcIndex+'.inputParams.'+paramIndex+'.formatValue'"
                                :rules="inputParam.rules"
                              >
                                <template v-if="'bool'.indexOf(inputParam.type) !== -1">
                                  <a-switch
                                    v-model="inputParam.formatValue"
                                    :checkedChildren="inputParam.metadata.trueText"
                                    :readOnly="func.executeConfig.mode === 'task'"
                                    :unCheckedChildren="inputParam.metadata.falseText"
                                  />
                                </template>
                                <template v-if="'int'.indexOf(inputParam.type) !== -1">
                                  <a-input-number
                                    v-model="inputParam.formatValue"
                                    :max="inputParam.metadata.max"
                                    :min="inputParam.metadata.min"
                                    :placeholder="'请输入' + inputParam.name"
                                    :readOnly="func.executeConfig.mode === 'task'"
                                  />
                                  <a-tag v-if="inputParam.metadata.unit" color="blue" style="margin-left: 10px" :title="inputParam.metadata.unitText">{{ inputParam.metadata.unit }}</a-tag>
                                </template>
                                <template v-if="'float,double'.indexOf(inputParam.type) !== -1">
                                  <a-input-number
                                    v-model="inputParam.formatValue"
                                    :max="inputParam.metadata.maxValue"
                                    :min="inputParam.metadata.minValue"
                                    :placeholder="'请输入' + inputParam.name"
                                    :precision="inputParam.metadata.accuracy"
                                    :readOnly="func.executeConfig.mode === 'task'"
                                    style="width: auto"
                                  />
                                  <a-tag v-if="inputParam.metadata.unit" color="blue" style="margin-left: 10px" :title="inputParam.metadata.unitText">{{ inputParam.metadata.unit }}</a-tag>
                                </template>
                                <template v-if="'string,ip,ipPort,address'.indexOf(inputParam.type) !== -1">
                                  <a-input
                                    v-model="inputParam.formatValue"
                                    :placeholder="'请输入' + inputParam.name"
                                    :readOnly="func.executeConfig.mode === 'task'"
                                  ></a-input>
                                </template>
                                <template v-if="'array'.indexOf(inputParam.type) !== -1">
                                  <a-textarea
                                    v-model="inputParam.formatValue"
                                    :placeholder="'请输入' + inputParam.name"
                                    :readOnly="func.executeConfig.mode === 'task'"
                                    :rows="3"
                                    allowClear
                                  ></a-textarea>
                                </template>
                                <template v-if="'vector3'.indexOf(inputParam.type) !== -1">
                                  <a-input
                                    v-model="inputParam.formatValue"
                                    :placeholder="'请输入' + inputParam.name+'值'"
                                    :readOnly="func.executeConfig.mode === 'task'"
                                    allowClear
                                  ></a-input>
                                </template>
                              </a-form-model-item>
                            </template>
                          </a-card>
                          <a-card v-if="func.executeConfig" size="small" style="margin-top: 16px" title="执行配置">
                            <template slot="extra" class="table-page-search-submitButtons" style="float: left;overflow: hidden;">
                              <a-popconfirm :title="func.executeConfig.isRunning ? '确定结束吗?' : '确定执行吗?'" @confirm="invokeFunction(funcIndex, !func.executeConfig.isRunning)">
                                <a-button v-if="func.executeConfig.mode === 'debug'" size="small" type="primary">调试</a-button> &nbsp;
                                <template v-if="func.executeConfig.mode === 'task'">
                                  <a-button v-if="!func.executeConfig.isRunning" ghost size="small" type="primary">执行</a-button>
                                  <a-button v-if="func.executeConfig.isRunning" ghost size="small" type="danger">结束</a-button>
                                </template>
                              </a-popconfirm>
                            </template>
                            <a-form-model-item ref="mode" label="执行模式">
                              <template slot="help">
                                <li>调试模式：输入参数可修改，可同步可异步，只执行1次</li>
                                <li>任务模式：输入参数不可修改，只能异步</li>
                              </template>
                              <a-radio-group v-model="func.executeConfig.mode" @change="e => executeModeChange(e.target.value, funcIndex)">
                                <a-radio value="debug">调试模式</a-radio>
                                <a-radio value="task">任务模式</a-radio>
                              </a-radio-group>
                            </a-form-model-item>
                            <a-form-model-item
                              ref="cron"
                              :prop="`functions[${funcIndex}].executeConfig.cron`"
                              :rules="{
                                  required: func.executeConfig.mode==='task',
                                  message: '请编辑任务执行周期',
                                  trigger: 'blur'
                                }"
                              label="任务周期"
                            >
                              {{ func.executeConfig.cron }}
                              <j-cron
                                v-model="func.executeConfig.cron"
                                :disabled="func.executeConfig.mode==='debug'"
                                @change="val => executeCornChange(val, funcIndex)"
                              ></j-cron>
                            </a-form-model-item>
                            <a-form-model-item ref="isSync" label="是否同步">
                              <a-switch
                                v-model="func.isSync"
                                :disabled="func.executeConfig.mode==='task'"
                                checkedChildren="同步"
                                unCheckedChildren="异步"
                              />
                            </a-form-model-item>
                            <a-form-model-item label="返回值">
                              {{func.outputParam}}
                            </a-form-model-item>
                          </a-card>
                        </a-tab-pane>
                      </template>
                    </a-tabs>
                  </a-form-model>
              </a-card>
            </a-tab-pane>
            <a-tab-pane key="alertConfig" tab="警告配置">
              <a-card>
                <a-tabs default-active-key="config" @change="alarmTabsChanged">
                  <a-tab-pane key="config" tab="告警设置">
                    <AlarmConfigList ref="alarmConfigList" :instanceId="model.instance.id"></AlarmConfigList>
                  </a-tab-pane>
                  <a-tab-pane key="record" force-render tab="告警记录">
                    <alarm-record-list ref="alarmRecordList" :instanceId="model.instance.id"></alarm-record-list>
                  </a-tab-pane>
                </a-tabs>
              </a-card>
            </a-tab-pane>
          </a-tabs>
        </template>
      </a-page-header>
    </a-spin>
  </j-modal>
</template>

<script>
import ChartCard from '@/components/ChartCard'
import DashChart from '@/components/chart/DashChartDemo'
import MiniArea from '@/components/chart/MiniArea'
import MiniBar from '@/components/chart/MiniBar'
import MiniProgress from '@/components/chart/MiniProgress'
import { getAction, httpAction } from '@api/manage'
import JSearchSelectTag from '@/components/dict/JSearchSelectTag'
import JSelectDepart from '@/components/jeecgbiz/JSelectDepart'
import JDictSelectTag from '@/components/dict/JDictSelectTag'
import DataReportList from './modules/detail/DataReportList'
import JCron from '@/components/jeecg/JCron'
import AlarmConfigList from './modules/detail/AlarmConfigList.vue'
import JModal from '@/components/jeecg/JModal'
import AlarmRecordList from './modules/detail/AlarmReportList'
import DataReportChart from '@views/iotcp/device/instance/modules/detail/DataReportChart'

export default {
  name: 'DeviceInstanceDetail',
  components: {
    DataReportChart,
    AlarmRecordList,
    AlarmConfigList,
    DataReportList,
    DashChart,
    ChartCard,
    MiniArea,
    MiniBar,
    MiniProgress,
    JSearchSelectTag,
    JSelectDepart,
    JDictSelectTag,
    JCron,
    JModal
  },
  data() {
    return {
      form: this.$form.createForm(this),
      confirmLoading: false,
      visible: false,
      fullscreen: true,
      switchFullscreen: true,

      visualOptTypes: [{
        value: 'switch',
        text: '开关'
      }, {
        value: 'btnWithParam',
        text: '按钮(有参)'
      }, {
        value: 'btnNoParam',
        text: '按钮(无参)'
      }],
      model: {},
      labelCol: {
        xs: { span: 24 },
        sm: { span: 4 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      avatar: 'https://gw.alipayobjects.com/zos/rmsportal/RzwpdLnhmvDJToTdfDPe.png',
      // extraImage: 'https://gw.alipayobjects.com/zos/rmsportal/RzwpdLnhmvDJToTdfDPe.png',
      rules: {
        name: [
          { required: true, message: '请输入实例名称!' },
          { min: 3, max: 30, message: '实例名称长度为3-30个字符' }
        ],
        modelBy: [{ required: true, message: '请选择设备模型!' }],
        sysOrgCode: [{ required: true, message: '请输入所属机构!' }],
        sceneBy: [{ required: true, message: '请选择所属场景!' }],
        sceneSchemeBy: [{ required: true, message: '请选择场景方案!' }]
      },
      url: {
        detail: 'device/instance/detail',
        invokeFunctionStart: 'device/instance/invokeFunctionStart'
      }
    }
  },
  methods: {
    executeModeChange(value, funcIndex) {
      console.log(value, funcIndex)
      this.$forceUpdate()
    },
    executeCornChange(value, funcIndex) {
      console.log(value, funcIndex)
      this.model.functions[funcIndex].executeConfig.cron = value
      this.$forceUpdate()
    },
    alarmTabsChanged(key) {
      console.log(key, this.model.instance.id)
    },
    validatorPattern(type, metadata) {
      let validatorPattern = {}
      if (type === 'array') {
        console.log(metadata)
        switch (metadata.arrayType) {
          case 'byte':
            validatorPattern.pattern = `^([0-9a-fA-F]{2}${metadata.arraySplit}){${metadata.arraySize - 1}}[0-9a-fA-F]{2}$`
            validatorPattern.message = `请输入${metadata.arraySize}位byte类型以${metadata.arraySplit === ' ' ? '空格' : metadata.arraySplit}为分隔符的数组`
            break
          case 'int':
            validatorPattern.pattern = `^([0-9]${metadata.arraySplit}){${metadata.arraySize - 1}}[0-9]$`
            break
          default:
            validatorPattern.pattern = `^(.${metadata.arraySplit}){${metadata.arraySize - 1}}.$`
        }
      } else if (type === 'ipPort') {
        validatorPattern = {
          pattern:
            '^(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\:\\d{2,6}$',
          message: '请正确输入TCP地址[IP:PORT]',
          trigger: 'blur'
        }
      } else if (type === 'int') {
        validatorPattern = { type: 'number' }
      } else if (type === 'float') {
        validatorPattern = { type: 'number' }
      } else if (type === 'double') {
        validatorPattern = { type: 'number' }
      } else if (type === 'long') {
        validatorPattern = { type: 'number' }
      } else if (type === 'vector3') {
        return {
          pattern: '^(\\-|\\+)?\\d+(\\.\\d+)?,(\\-|\\+)?\\d+(\\.\\d+)?,(\\-|\\+)?\\d+(\\.\\d+)?$',
          message: '请按正确格式输入三维向量数据',
          trigger: 'blur'
        }
      }

      return validatorPattern
    },
    /**
     * 手动下线
     * @param instanceId
     */
    forceOffline(instanceId) {
      let scope = this
      getAction(`device/instance/manuallyOffline/${instanceId}`).then(res => {
        if (res.success) {
          this.$message.success(res.message)
          scope.detail(instanceId)
        }
      })

    },
    refresh(instanceId) {
      this.detail(instanceId)
    },
    detail(instanceId) {
      let scope = this
      this.visible = true
      this.confirmLoading = true
      getAction(this.url.detail + '/' + instanceId)
        .then(res => {
          if (res.success) {
            scope.model = res.result
            scope.model.functions = res.result.functions.map((func, i) => {
              if(!func.id) {
                delete res.result.functions[i]
                return ;
              }
              func['executeConfig'] = Object.assign({
                mode: 'task',
                cron: '3/5 * * * * ? *',
                isRunning: false
              }, func.executeConfig);
              // 追加校验规则
              func['inputParams'] = func['inputParams'].filter(filter => filter.direction === 'input')
                // 过滤操作输入
              func['inputParams']
                .filter(filter => filter.inputMode === 'opt_input')
                .map(inputParam => {
                  if('int,float,double,long'.includes(inputParam.type)) {
                    // 数字类型的数据
                    inputParam.formatValue = inputParam.value
                  }
                  inputParam['rules'] = []
                  inputParam.rules.push({ required: true, trigger: 'blur', message: '请填写' + inputParam.inputModeText + '!' })
                  inputParam.rules.push(scope.validatorPattern(inputParam.type, inputParam.metadata))
                  // 删除metadata
                  // delete inputParam.metadata
                })
              func['outputParam'] = func['inputParams'].filter(filter => filter.direction === 'output')[0] || {}

              return func
            })

            console.log(scope.model.functions)
            scope.model.instanceDatas = res.result.instanceDatas.filter(data => data.rwAuthor === 'r')
          }
        })
        .finally(() => {
          setTimeout(() => {
            scope.confirmLoading = false
          }, 200)
        })
    },
    // 调用功能
    invokeFunction(funcIndex = 0, isRunning = false) {
      this.confirmLoading = true
      const scope = this
      this.$refs.functionInvokeForm.validate(valid => {
        if (valid) {
          let function_ = JSON.parse(JSON.stringify(this.model.functions[funcIndex]))
          function_['code'] = function_.code
          function_['executeConfig'].isRunning = isRunning
          function_['instanceId'] = scope.model.instance.id
          function_['modelId'] = scope.model.model.id
          function_.inputParams.map(param => {
            delete param.rules
            // delete param.metadata
            delete param.metadata.arrayTypeText
            delete param.metadata.typeText
          })
          delete function_.outputParam

          console.log('提交表单', function_)

          /**
           * 1、网络请求功能：后台执行，调用网络服务
           * 2、设备移动、缩放、旋转：调用mqtt服务，实时修改3D页面的设备状态
           */
          httpAction(this.url.invokeFunctionStart, function_, 'post').then(res => {
              if (res.success) {
                if(function_.executeConfig.mode === 'task'){
                  scope.model.functions[funcIndex].executeConfig.isRunning = isRunning
                }
                scope.$forceUpdate()
                scope.$message.success(res.message)
              } else {
                scope.$message.error(res.message)
              }
              scope.confirmLoading = false
              scope.model.functions[funcIndex].outputParam = res.result || res.message
          })

        } else {
          scope.confirmLoading = false
        }
      })
    },
    handleCancel() {
      this.model = {}
      this.$emit('close')
      this.visible = false
      this.$forceUpdate()
    }
  }
}
</script>

<style lang="less" scoped>
.ant-modal-body {
  background-color: #a1a4ad;
}
</style>
